package com.dingding.manager.core.shiro.factory;

import java.util.ArrayList;
import java.util.List;

import org.apache.shiro.authc.DisabledAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.hibernate.criterion.Restrictions;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.dingding.manager.common.beans.sys.Organization;
import com.dingding.manager.common.beans.sys.SysMenu;
import com.dingding.manager.common.beans.sys.SysRole;
import com.dingding.manager.common.beans.sys.SysUser;
import com.dingding.manager.common.beans.sys.SysUserRole;
import com.dingding.manager.common.dao.Db;
import com.dingding.manager.common.vo.OrganizationNode;
import com.dingding.manager.core.shiro.ShiroKit;
import com.dingding.manager.core.shiro.ShiroUser;
import com.dingding.manager.core.util.SpringContextHolder;
import com.dingding.manager.core.util.ToolUtil;
import com.dingding.manager.modules.system.sql.OrganizationSQL;
import com.dingding.manager.modules.system.util.DataScopeUtil;

@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class ShiroFactroy implements IShiro {

	public static IShiro me() {
		return SpringContextHolder.getBean(IShiro.class);
	}

	@Override
	public SysUser user(String account) {
		SysUser user = Db.queryCriterionFirst(SysUser.class, Restrictions.eq("loginName", account));
		// 账号不存在
		if (null == user) {
			throw new UnknownAccountException();
		}
		// 账号被冻结
		if (user.getUserStatus() == 0) {
			throw new DisabledAccountException();
		}
		return user;
	}

	@Override
	public ShiroUser shiroUser(SysUser user) {
		//角色id集合
		List<SysUserRole> userRoleList = Db.queryCriterionList(SysUserRole.class,
				Restrictions.eq("sysUserId", user.getSysUserId()));
		List<Integer> roles = new ArrayList<Integer>();
		
		for (SysUserRole role : userRoleList) {
			roles.add(role.getSysRoleId());
		}
		//根据角色id查询角色信息
		List<String> roleNames = new ArrayList<String>();
		for (Integer roleId : roles) {
			SysRole sysRole = Db.findById(roleId, SysRole.class);
			roleNames.add(sysRole.getRoleName());
		}
		//获取机构和部门信息
		Organization company = Db.findById(user.getCompanyId(), Organization.class);
		Organization dept = Db.findById(user.getDeptId(), Organization.class);
		
		return new ShiroUser(user.getSysUserId(), user.getLoginName(), user.getTrueName(), user.getCompanyId(),
				user.getDeptId(), roles,company.getOrganizationName(),dept.getOrganizationName(),roleNames);
	}

	@Override
	public List<String> findPermissionsByRoleId(Integer roleId) {
		StringBuilder sql = new StringBuilder();
		sql.append("select m.permission from dd_sys_role_menu rm ");
		sql.append("inner join dd_sys_menu m on m.sysMenuId = rm.sysMenuId ");
		sql.append("inner join dd_sys_role r on r.sysRoleId = rm.sysRoleId ");
		sql.append("where rm.sysRoleId = ? ");

		List<SysMenu> menus = Db.querySqlList(SysMenu.class, sql.toString(), roleId);
		List<String> permissions = new ArrayList<String>();
		for (SysMenu sysMenu : menus) {
			permissions.add(sysMenu.getPermission());
		}
		return permissions;
	}

	@Override
	public String findRoleNameByRoleId(Integer roleId) {
		SysRole role = Db.queryCriterionFirst(SysRole.class, Restrictions.eq("sysRoleId", roleId));
		return role.getRoleEnName();
	}

	@Override
	public SimpleAuthenticationInfo info(ShiroUser shiroUser, SysUser user, String realmName) {
		String credentials = user.getPassword();
		return new SimpleAuthenticationInfo(shiroUser, credentials, realmName);
	}

	/**
	 * @Description: 获取用户所能访问的公司集合
	 * @date 2016年12月27日 下午4:26:24
	 * @author SUNZHICHENG
	 * @since V2.6.2
	 */
	@Override
	public List<Organization> getOrganizationList() {
		
		  StringBuilder sql=new StringBuilder(OrganizationSQL.QUERY_ORGANIZATION_LIST);
		  //公司id集合
		  List<Integer> organizationIds=new ArrayList<Integer>();
		  //部门id集合
		  List<Integer> deptIds=new ArrayList<Integer>();
		  

		  //获取当前用户所属的公司和其子公司
		  List<Organization> organizationList = getOrganizations();
		 if (organizationList.size()>0) {
			 for (Organization organization : organizationList) {
					organizationIds.add(organization.getOrganizationId());
				}
		 }
		 
		 //获取当前用户所属的部门和其子部门
		 List<Organization> depts = getDepts();
		 
		 if (depts.size()>0) {
			for (Organization organization : depts) {
				deptIds.add(organization.getOrganizationId());
			}
			
		 }
		 
		 if (organizationList.size() == 0 ) {
			return organizationList;
		}
		 if (depts.size()== 0) {
			return depts;
		}
		 
		 sql.append(DataScopeUtil.dataScopeFilter(ShiroKit.getUser(), "m",  "",organizationIds,deptIds));
		 return Db.querySqlList(Organization.class, sql.toString());

	}
	
	/**
	 * @Description:获取当前用户所属的公司和其子公司 
	 * @date 2016年12月28日 下午7:45:28
	 * @author SUNZHICHENG 
	 * @since V2.6.3
	 */
	public List<Organization> getOrganizations() {
		// 获取所有公司列表
		List<Organization> querySqlList = Db.querySqlList(Organization.class, OrganizationSQL.QUERY_ORGANIZATION_LIST);
		//当前用户所属公司id
		
		Integer companyId = ShiroKit.getUser().getCompanyId();
		
		//获取当前登录用户所属公司
		Organization organization = Db.findById(companyId, Organization.class);
		
		OrganizationNode organizationNode = new OrganizationNode();
		
		//获取当前用户所属公司下的所有子公司列表
		List<Organization> organizationList = organizationNode.recurorganizationList(companyId, querySqlList);
		//添加当前公司到集合
		if (ToolUtil.isNotEmpty(organization.getOrganizationStatus()) && organization.getOrganizationStatus() == 1 ) {
			organizationList.add(organization);
		}
		
		return organizationList;
	}
	
	/**
	 * @Description:获取当前用户所属的部门和其子部门
	 * @date 2016年12月28日 下午7:45:28
	 * @author SUNZHICHENG 
	 * @since V2.6.3
	 */
	public List<Organization> getDepts(){
		// 获取所有公司列表
		List<Organization> querySqlList = Db.querySqlList(Organization.class, OrganizationSQL.QUERY_ORGANIZATION_LIST);
		//当前用户所属部门id
		
		Integer deptId = ShiroKit.getUser().getDeptId(); 
		Organization dept = Db.findById(deptId, Organization.class);
		
		OrganizationNode organizationNode = new OrganizationNode();
		//获取当前用户所属部门下的所有子公司列表
		List<Organization> organizationList = organizationNode.recurorganizationList(deptId, querySqlList);
		
		//添加当前部门到集合
		if (ToolUtil.isNotEmpty(dept.getOrganizationStatus()) && dept.getOrganizationStatus() == 1) {
			organizationList.add(dept);
		}
		
		return organizationList;
	}


}
